// @Name    : cai_request_cancel_group
// @author  : simon
// @date    : 2025/5/21 09:26
// @desc    : 请求取消组合管理
// 能够同时取消多个相关的请求，例如在一个页面离开时取消所有未完成的请求，或者在执行一系列相关请求时，
// 如果其中一个失败，可以取消其他请求。这需要一种机制来管理多个CancelToken，或者使用一个父CancelToken来管理子CancelToken。
// Dio允许每个请求关联一个CancelToken，调用cancel()方法可以取消请求。为了实现组合取消，
// 可能需要一个主CancelToken，它能够取消所有关联的子请求。或者，可以维护一个组ID，将多个CancelToken关联到同一个组，当需要取消时，遍历并取消所有相关token。
/*
亮点：
1.分层取消架构：
创建 CaiRequestCancelGroup 作为组合容器
支持令牌自动回收机制
实现三级取消控制（单个/组/全局）

2.智能生命周期管理：
token.whenCancel.then((_) => _tokens.remove(token));
自动清理已完成请求的令牌

3.复合请求支持：实现原子性批量请求，任一失败自动取消组内其他请求
Future<List<Response>> requestAll()
4.增强型错误处理：
区分用户主动取消与系统级取消

5.线程安全设计：
使用不可变列表副本进行遍历操作

 */

import 'package:dio/dio.dart';

class CaiRequestCancelGroup {

  final _tokens = <CancelToken>[];
  bool _isCanceled = false;

  /// 创建新令牌并加入组
  CancelToken createToken() {
    if (_isCanceled) {
      throw StateError('Cannot create token in canceled group');
    }
    final token = CancelToken();
    _tokens.add(token);
    token.whenCancel.then((_) => _tokens.remove(token));
    return token;
  }

  /// 取消组内所有请求
  void cancel([dynamic reason]) {
    _isCanceled = true;
    for (final token in _tokens.toList()) {
      if (!token.isCancelled) {
        token.cancel(reason ?? 'GroupCancel');
      }
    }
    _tokens.clear();
  }

  /// 获取当前活跃请求数
  int get activeCount => _tokens.length;
}


/*
1.页面级应用：
class NewsPageState extends State {
  late final CaiRequestCancelGroup _pageGroup;

  @override
  void initState() {
    super.initState();
    _pageGroup = CaiRequestCancelGroup();
    _loadData();
  }

  void _loadData() async {
    await CaiHttpRequest.shared.request(..., cancelGroup: _pageGroup);
  }

  @override
  void dispose() {
    _pageGroup.cancel();
    super.dispose();
  }
}

2.复杂操作流程：
void multiStepOperation() async {
  final workflowGroup = CaiRequestCancelGroup();

  try {
    final step1 = await service.request(..., cancelGroup: workflowGroup);
    final step2 = await service.request(..., cancelGroup: workflowGroup);
    final step3 = await service.request(..., cancelGroup: workflowGroup);
  } catch (e) {
    workflowGroup.cancel('OperationFailed');
  }
}
3.竞态条件处理：（比如根据条件返回当前页面到上一页，并发送通知让上一页请求更新数据）
直接在发送通知之前取消请求，再发送通知组。
class SearchService {
  final RequestCancelGroup _searchGroup = RequestCancelGroup();

  void search(String query) async {
    _searchGroup.cancel('NewSearch');
    await service.request(..., cancelGroup: _searchGroup);
  }
}
 */